// 版权所有2011 Go作者。版权所有。
// 此源代码的使用受BSD样式的约束
// 可以在许可证文件中找到的许可证。

package types2

import (
	"cmd/compile/internal/syntax"
	"fmt"
	"sync/atomic"
)

// 类型代表一种Go类型。
// 所有类型都实现类型接口。
type Type interface {
	// 基础返回类型的基础类型
	// 没有以下转发链。仅用于
	// 客户端软件包（此处用于向后兼容）。
	Underlying() Type

	// String返回类型的字符串表示形式。
	String() string
}

// BasicKind描述了基本类型的类型。
type BasicKind int

const (
	Invalid BasicKind = iota // 类型无效

	// 预先声明的类型
	Bool
	Int
	Int8
	Int16
	Int32
	Int64
	Uint
	Uint8
	Uint16
	Uint32
	Uint64
	Uintptr
	Float32
	Float64
	Complex64
	Complex128
	String
	UnsafePointer

	// 非类型化值的类型
	UntypedBool
	UntypedInt
	UntypedRune
	UntypedFloat
	UntypedComplex
	UntypedString
	UntypedNil

	// 别名
	Byte = Uint8
	Rune = Int32
)

// BasicInfo是一组描述基本类型属性的标志。
type BasicInfo int

// 基本类型的属性。
const (
	IsBoolean BasicInfo = 1 << iota
	IsInteger
	IsUnsigned
	IsFloat
	IsComplex
	IsString
	IsUntyped

	IsOrdered   = IsInteger | IsFloat | IsString
	IsNumeric   = IsInteger | IsFloat | IsComplex
	IsConstType = IsBoolean | IsNumeric | IsString
)

// Basic表示基本类型。
type Basic struct {
	kind BasicKind
	info BasicInfo
	name string
}

// Kind返回基本类型b的类型。
func (b *Basic) Kind() BasicKind { return b.kind }

// Info返回关于基本类型b的属性的信息。
func (b *Basic) Info() BasicInfo { return b.info }

// Name返回基本类型b的名称。
func (b *Basic) Name() string { return b.name }

// 数组表示数组类型。
type Array struct {
	len  int64
	elem Type
}

// NewArray返回给定元素类型和长度的新数组类型。
// 负长度表示未知长度。
func NewArray(elem Type, len int64) *Array { return &Array{len: len, elem: elem} }

// Len返回数组a的长度。
// 负结果表示长度未知。
func (a *Array) Len() int64 { return a.len }

// Elem返回数组a的元素类型。
func (a *Array) Elem() Type { return a.elem }

// 切片表示切片类型。
type Slice struct {
	elem Type
}

// NewSlice返回给定元素类型的新切片类型。
func NewSlice(elem Type) *Slice { return &Slice{elem: elem} }

// Elem返回切片s的元素类型。
func (s *Slice) Elem() Type { return s.elem }

// 结构表示结构类型。
type Struct struct {
	fields []*Var
	tags   []string // 字段标签；如果没有标签，则为零
}

// NewStruct返回具有给定字段和相应字段标记的新结构。
// 如果索引为i的字段有一个标记，则标记[i]必须是该标记，但len（标记）可能是
// 仅当需要保持索引i最大的标签时。因此
// 如果没有字段具有标记，则标记可能为零。
func NewStruct(fields []*Var, tags []string) *Struct {
	var fset objset
	for _, f := range fields {
		if f.name != "_" && fset.insert(f) != nil {
			panic("multiple fields with the same name")
		}
	}
	if len(tags) > len(fields) {
		panic("more tags than fields")
	}
	return &Struct{fields: fields, tags: tags}
}

// NumFields返回结构中的字段数（包括空白字段和嵌入字段）。
func (s *Struct) NumFields() int { return len(s.fields) }

// 字段返回0<=i<NumFields（）的第i个字段。
func (s *Struct) Field(i int) *Var { return s.fields[i] }

// 标记返回0<=i<NumFields（）的第i个字段标记。
func (s *Struct) Tag(i int) string {
	if i < len(s.tags) {
		return s.tags[i]
	}
	return ""
}

// 指针表示指针类型。
type Pointer struct {
	base Type // 元素类型
}

// NewPointer返回给定元素（基）类型的新指针类型。
func NewPointer(elem Type) *Pointer { return &Pointer{base: elem} }

// Elem返回给定指针p的元素类型。
func (p *Pointer) Elem() Type { return p.base }

// 元组表示变量的有序列表；nil*元组是有效（空）元组。
// 元组用作签名的组件并表示多个签名的类型
// 作业；他们不是一流的围棋。
type Tuple struct {
	vars []*Var
}

// NewTuple为给定变量返回一个新的元组。
func NewTuple(x ...*Var) *Tuple {
	if len(x) > 0 {
		return &Tuple{vars: x}
	}
	// TODO（gri）不使用（*Tuple）（nil）指针表示空元组；
	// 这太微妙了，会引起问题。
	return nil
}

// Len返回元组t的数量变量。
func (t *Tuple) Len() int {
	if t != nil {
		return len(t.vars)
	}
	return 0
}

// At返回元组t的第i个变量。
func (t *Tuple) At(i int) *Var { return t.vars[i] }

// 签名表示（非内置）函数或方法类型。
// 比较身份签名时忽略接收者。
type Signature struct {
	// 我们需要将作用域保留在签名中（而不是传递它）
	// 并将其存储在Func对象中），因为在检查函数类型时
	// 我们称之为常规类型检查器，它返回一个常规类型。
	// 然后，我们解压*签名并使用文本体的作用域。
	rparams  []*TypeName // 从左到右的接收器类型参数；还是零
	tparams  []*TypeName // 类型参数从左到右；还是零
	scope    *Scope      // 函数作用域，用于包本地签名
	recv     *Var        // 如果不是方法，则为零
	params   *Tuple      // （输入）从左到右的参数；还是零
	results  *Tuple      // （传出）从左到右的结果；还是零
	variadic bool        // 如果最后一个参数的类型为…T形式（或字符串，仅用于附加内置）
}

// NewSignature为给定的接收器返回新的函数类型、参数、，
// 和结果，其中任何一个都可能为零。如果设置了VARIDIC，则该功能
// 是可变的，它必须至少有一个参数和最后一个参数
// 必须是未命名的切片类型。
func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature {
	if variadic {
		n := params.Len()
		if n == 0 {
			panic("types2.NewSignature: variadic function must have at least one parameter")
		}
		if _, ok := params.At(n - 1).typ.(*Slice); !ok {
			panic("types2.NewSignature: variadic parameter must be of unnamed slice type")
		}
	}
	return &Signature{recv: recv, params: params, results: results, variadic: variadic}
}

// Recv返回签名s的接收者（如果是方法），如果是
// 作用在比较签名的标识时，将忽略此选项。
// None
// 对于抽象方法，Recv返回封闭接口
// 作为*命名或*接口。由于嵌入，接口可能会
// 包含其接收器类型为不同接口的方法。
func (s *Signature) Recv() *Var { return s.recv }

// TParams返回签名s或nil的类型参数。
func (s *Signature) TParams() []*TypeName { return s.tparams }

// RParams返回签名s或nil的接收方类型参数。
func (s *Signature) RParams() []*TypeName { return s.rparams }

// SetTParams设置签名的类型参数。
func (s *Signature) SetTParams(tparams []*TypeName) { s.tparams = tparams }

// Params返回签名s的参数，或nil。
func (s *Signature) Params() *Tuple { return s.params }

// 结果返回签名s或nil的结果。
func (s *Signature) Results() *Tuple { return s.results }

// Variadic报告签名s是否可变。
func (s *Signature) Variadic() bool { return s.variadic }

// 总和表示一组可能的类型。
// 总和当前用于表示接口的类型列表
// 以及类型参数的基本类型；它们不是
// 一流的围棋。
type Sum struct {
	types []Type // 类型是唯一的
}

// NewSum返回一个由提供的
// 类型（如果有多个）。如果正好有一个
// 类型，则返回该类型。如果类型列表为空
// 结果是零。
func NewSum(types []Type) Type {
	if len(types) == 0 {
		return nil
	}

	// 如果类型包含总和类型，会发生什么情况？
	// 我们是否将类型列表展平？现在我们检查一下
	// 还有恐慌。这不应该是可能的
	// 类型列表的当前用例。
	// TODO（gri）提出了求和类型的规则。
	for _, t := range types {
		if _, ok := t.(*Sum); ok {
			panic("sum type contains sum type - unimplemented")
		}
	}

	if len(types) == 1 {
		return types[0]
	}
	return &Sum{types: types}
}

// is报告t中的所有类型是否满足pred。
func (s *Sum) is(pred func(Type) bool) bool {
	if s == nil {
		return false
	}
	for _, t := range s.types {
		if !pred(t) {
			return false
		}
	}
	return true
}

// 接口表示接口类型。
type Interface struct {
	methods   []*Func // 显式声明方法的有序列表
	types     Type    // 使用类型列表声明的（可能是Sum）类型（TODO（gri）需要更好的字段名）
	embeddeds []Type  // 显式嵌入类型的有序列表

	allMethods []*Func // 此接口中声明或嵌入的方法的有序列表（TODO（gri）：替换为mset）
	allTypes   Type    // 所有嵌入类型和本地声明类型的交集（TODO（gri）需要更好的字段名）

	obj Object // 定义此接口的类型声明；或零（用于更好的错误消息）
}

// 解包将类型解包到类型列表中。
// TODO（gri）尝试消除对该功能的需求。
func unpack(typ Type) []Type {
	if typ == nil {
		return nil
	}
	if sum := asSum(typ); sum != nil {
		return sum.types
	}
	return []Type{typ}
}

// is报告接口t是否表示所有满足pred的类型。
func (t *Interface) is(pred func(Type) bool) bool {
	if t.allTypes == nil {
		return false // 我们必须至少有一种类型！（是臭虫）
	}
	for _, t := range unpack(t.allTypes) {
		if !pred(t) {
			return false
		}
	}
	return true
}

// emptyInterface表示空（已完成）接口
var emptyInterface = Interface{allMethods: markComplete}

// markComplete用于将空接口标记为完全
// 通过将allMethods字段设置为非nil空切片进行设置。
var markComplete = make([]*Func, 0)

// NewInterface为给定的方法和嵌入类型返回一个新的（不完整的）接口。
// 每个嵌入类型必须具有接口类型的基础类型。
// NewInterface拥有所提供方法的所有权，并且可以通过设置
// 接受者失踪。要计算接口的方法集，必须调用Complete。
// None
// 不推荐：改用NewInterfaceType，它允许任何（甚至是未定义的）接口类型
// 嵌入。对于嵌入别名类型名称的接口，这是必需的
// 未定义（文字）接口类型。
func NewInterface(methods []*Func, embeddeds []*Named) *Interface {
	tnames := make([]Type, len(embeddeds))
	for i, t := range embeddeds {
		tnames[i] = t
	}
	return NewInterfaceType(methods, tnames)
}

// NewInterfaceType为给定的方法和嵌入类型返回一个新的（不完整的）接口。
// 每个嵌入类型必须具有接口类型的基础类型（此属性不是
// 已验证定义的类型，这些类型可能正在设置过程中，但没有
// 还没有有效的基础类型）。
// NewInterfaceType拥有所提供方法的所有权，并且可以通过设置
// 接受者失踪。要计算接口的方法集，必须调用Complete。
func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface {
	if len(methods) == 0 && len(embeddeds) == 0 {
		return &emptyInterface
	}

	// 如有必要，设置方法接收器
	typ := new(Interface)
	for _, m := range methods {
		if sig := m.typ.(*Signature); sig.recv == nil {
			sig.recv = NewVar(m.pos, m.pkg, "", typ)
		}
	}

	// 所有嵌入式类型应为接口；但是，定义的类型
	// 可能还没有完全解决。仅验证未定义的类型
	// 是接口。这与
	// 修正#25301（问题#25596）。
	for _, t := range embeddeds {
		if _, ok := t.(*Named); !ok && !IsInterface(t) {
			panic("embedded type is not an interface")
		}
	}

	// API稳定性排序
	sortMethods(methods)
	sortTypes(embeddeds)

	typ.methods = methods
	typ.embeddeds = embeddeds
	return typ
}

// NumExplicitMethods返回接口t显式声明的方法数。
func (t *Interface) NumExplicitMethods() int { return len(t.methods) }

// ExplicitMethod返回接口t的第i个显式声明的方法，该方法的值为0<=i<t.NumExplicitMethods（）。
// 这些方法按其唯一Id排序。
func (t *Interface) ExplicitMethod(i int) *Func { return t.methods[i] }

// NumEmbeddeds返回接口t中嵌入类型的数量。
func (t *Interface) NumEmbeddeds() int { return len(t.embeddeds) }

// Embedded返回0<=i<t.NumEmbeddeds（）的第i个嵌入式定义（*命名）类型的接口t。
// 如果第i个嵌入类型不是已定义的类型，则结果为nil。
// None
// 不推荐：使用EmbeddedType，它不限于已定义（*命名）的类型。
func (t *Interface) Embedded(i int) *Named { tname, _ := t.embeddeds[i].(*Named); return tname }

// EmbeddedType返回0<=i<t.NumEmbeddeds（）的接口t的第i个嵌入类型。
func (t *Interface) EmbeddedType(i int) Type { return t.embeddeds[i] }

// NumMethods返回接口t的方法总数。
// 接口必须已完成。
func (t *Interface) NumMethods() int { t.assertCompleteness(); return len(t.allMethods) }

func (t *Interface) assertCompleteness() {
	if t.allMethods == nil {
		panic("interface is incomplete")
	}
}

// 方法返回0<=i<t.NumMethods（）的接口t的第i个方法。
// 这些方法按其唯一Id排序。
// 接口必须已完成。
func (t *Interface) Method(i int) *Func { t.assertCompleteness(); return t.allMethods[i] }

// Empty报告t是否为空接口。
func (t *Interface) Empty() bool {
	if t.allMethods != nil {
		// 界面完整-快速测试
		// 非nil allTypes可能仍然为空，并表示底部类型。
		return len(t.allMethods) == 0 && t.allTypes == nil
	}
	return !t.iterate(func(t *Interface) bool {
		return len(t.methods) > 0 || t.types != nil
	}, nil)
}

// HasTypeList报告接口t是否有类型列表，可能来自嵌入类型。
func (t *Interface) HasTypeList() bool {
	if t.allMethods != nil {
		// 界面完整-快速测试
		return t.allTypes != nil
	}

	return t.iterate(func(t *Interface) bool {
		return t.types != nil
	}, nil)
}

// IsComparable报告接口t是否是或嵌入了预先声明的接口“可比较”。
func (t *Interface) IsComparable() bool {
	if t.allMethods != nil {
		// 界面完整-快速测试
		_, m := lookupMethod(t.allMethods, nil, "==")
		return m != nil
	}

	return t.iterate(func(t *Interface) bool {
		_, m := lookupMethod(t.methods, nil, "==")
		return m != nil
	}, nil)
}

// IsConstraint报告t.HasTypeList（）| | t.IsCompable（）。
func (t *Interface) IsConstraint() bool {
	if t.allMethods != nil {
		// 界面完整-快速测试
		if t.allTypes != nil {
			return true
		}
		_, m := lookupMethod(t.allMethods, nil, "==")
		return m != nil
	}

	return t.iterate(func(t *Interface) bool {
		if t.types != nil {
			return true
		}
		_, m := lookupMethod(t.methods, nil, "==")
		return m != nil
	}, nil)
}

// 使用t迭代调用f，然后使用t的任何嵌入接口递归地迭代调用f，直到f返回true。
// iterate报告对f的任何调用是否返回true。
func (t *Interface) iterate(f func(*Interface) bool, seen map[*Interface]bool) bool {
	if f(t) {
		return true
	}
	for _, e := range t.embeddeds {
		// e应该是一个接口，但要小心（它可能无效）
		if e := asInterface(e); e != nil {
			// 不允许循环接口，如“E型接口{E}”
			// 但它们仍然是构造的，我们需要检测这样的循环。
			if seen[e] {
				continue
			}
			if seen == nil {
				seen = make(map[*Interface]bool)
			}
			seen[e] = true
			if e.iterate(f, seen) {
				return true
			}
		}
	}
	return false
}

// IsSatifiedBy报告类型类型是否满足接口t的类型列表。
// 如果类型列表为空（不存在），则typ基本满足接口。
// TODO（gri）这不是个好名字。最终，我们应该有一个更全面的计划
// “implements”谓词。
func (t *Interface) isSatisfiedBy(typ Type) bool {
	t.Complete()
	if t.allTypes == nil {
		return true
	}
	types := unpack(t.allTypes)
	return includes(types, typ) || includes(types, under(typ))
}

// Complete计算接口的方法集。它必须由的用户调用
// 在接口的嵌入类型之后添加NewInterfaceType和NewInterface
// 完全定义，并且在以任何方式使用接口类型之前
// 形成其他类型。接口不能包含重复的方法或
// 恐慌发生了。完成返回接收器。
func (t *Interface) Complete() *Interface {
	// TODO（gri）使用Checker.completeInterface合并此方法
	if t.allMethods != nil {
		return t
	}

	t.allMethods = markComplete // 避免无限递归

	var todo []*Func
	var methods []*Func
	var seen objset
	addMethod := func(m *Func, explicit bool) {
		switch other := seen.insert(m); {
		case other == nil:
			methods = append(methods, m)
		case explicit:
			panic("duplicate method " + m.name)
		default:
			// 计算所有本地嵌入接口后检查方法签名
			todo = append(todo, m, other.(*Func))
		}
	}

	for _, m := range t.methods {
		addMethod(m, true)
	}

	allTypes := t.types

	for _, typ := range t.embeddeds {
		utyp := under(typ)
		etyp := asInterface(utyp)
		if etyp == nil {
			if utyp != Typ[Invalid] {
				panic(fmt.Sprintf("%s is not an interface", typ))
			}
			continue
		}
		etyp.Complete()
		for _, m := range etyp.allMethods {
			addMethod(m, false)
		}
		allTypes = intersect(allTypes, etyp.allTypes)
	}

	for i := 0; i < len(todo); i += 2 {
		m := todo[i]
		other := todo[i+1]
		if !Identical(m.typ, other.typ) {
			panic("duplicate method " + m.name)
		}
	}

	if methods != nil {
		sortMethods(methods)
		t.allMethods = methods
	}
	t.allTypes = allTypes

	return t
}

// 映射表示映射类型。
type Map struct {
	key, elem Type
}

// NewMap返回给定键和元素类型的新映射。
func NewMap(key, elem Type) *Map {
	return &Map{key: key, elem: elem}
}

// Key返回map m的键类型。
func (m *Map) Key() Type { return m.key }

// Elem返回map m的元素类型。
func (m *Map) Elem() Type { return m.elem }

// Chan表示一种通道类型。
type Chan struct {
	dir  ChanDir
	elem Type
}

// ChanDir值表示通道方向。
type ChanDir int

// 通道的方向由这些常数之一表示。
const (
	SendRecv ChanDir = iota
	SendOnly
	RecvOnly
)

// NewChan返回给定方向和元素类型的新通道类型。
func NewChan(dir ChanDir, elem Type) *Chan {
	return &Chan{dir: dir, elem: elem}
}

// Dir返回通道c的方向。
func (c *Chan) Dir() ChanDir { return c.dir }

// Elem返回通道c的元素类型。
func (c *Chan) Elem() Type { return c.elem }

// TODO（gri）清理下面的命名结构；特别是fromRHS字段（我们可以使用底层吗？）。

// 已命名的表示已命名（已定义）的类型。
type Named struct {
	check      *Checker    // 对于正在实施的命名
	info       typeInfo    // 用于周期检测
	obj        *TypeName   // 相应的声明对象
	orig       *Named      // 原始的、未实例化的类型
	fromRHS    Type        // 类型（在声明的右侧）此*命名类型派生自（用于周期报告）
	underlying Type        // 可能是在安装过程中命名的*；从未有过一次完全设置的*命名
	tparams    []*TypeName // 类型参数，或nil
	targs      []Type      // 类型参数（实例化后）或nil
	methods    []*Func     // 为此类型声明的方法（不是此类型的方法集）；签名是惰性地进行类型检查的
}

// NewNamed返回给定类型名、基础类型和关联方法的新命名类型。
// 如果给定的类型名obj还没有类型，则将其类型设置为返回的命名类型。
// 基础类型不能是*命名的。
func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named {
	if _, ok := underlying.(*Named); ok {
		panic("types2.NewNamed: underlying type must not be *Named")
	}
	return (*Checker)(nil).newNamed(obj, nil, underlying, nil, methods)
}

// newNamed与newNamed类似，但有一个*检查器接收器和附加的orig参数。
func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams []*TypeName, methods []*Func) *Named {
	typ := &Named{check: check, obj: obj, orig: orig, fromRHS: underlying, underlying: underlying, tparams: tparams, methods: methods}
	if typ.orig == nil {
		typ.orig = typ
	}
	if obj.typ == nil {
		obj.typ = typ
	}
	return typ
}

// Obj返回命名类型t的类型名。
func (t *Named) Obj() *TypeName { return t.obj }

// Orig返回从中派生实例化类型的原始泛型类型。
// 如果t不是实例化类型，则结果是t。
func (t *Named) Orig() *Named { return t.orig }

// TODO（gri）提出了更好的表示和API来区分
// 在参数化实例化类型和非实例化类型之间。

// TParams返回命名类型t或nil的类型参数。
// 对于（最初）参数化的类型，即使它被实例化，结果也是非nil的。
func (t *Named) TParams() []*TypeName { return t.tparams }

// SetTParams设置命名类型t的类型参数。
func (t *Named) SetTParams(tparams []*TypeName) { t.tparams = tparams }

// TArgs在实例化命名类型t后返回类型参数，如果未实例化，则返回nil。
func (t *Named) TArgs() []Type { return t.targs }

// SetTArgs设置命名类型t的类型参数。
func (t *Named) SetTArgs(args []Type) { t.targs = args }

// NumMethods返回其接收器名为t类型的显式方法数。
func (t *Named) NumMethods() int { return len(t.methods) }

// 方法返回0<=i<t.NumMethods（）的命名类型为t的第i个方法。
func (t *Named) Method(i int) *Func { return t.methods[i] }

// SetUnderground设置基础类型并将t标记为完整。
func (t *Named) SetUnderlying(underlying Type) {
	if underlying == nil {
		panic("types2.Named.SetUnderlying: underlying type must not be nil")
	}
	if _, ok := underlying.(*Named); ok {
		panic("types2.Named.SetUnderlying: underlying type must not be *Named")
	}
	t.underlying = underlying
}

// AddMethod添加方法m，除非它已在方法列表中。
func (t *Named) AddMethod(m *Func) {
	if i, _ := lookupMethod(t.methods, m.pkg, m.name); i < 0 {
		t.methods = append(t.methods, m)
	}
}

// 注意：这是uint32而不是uint64，因为
// 相应的64位原子指令不可用
// 在所有平台上。
var lastId uint32

// nextId返回一个单调递增1的值
// 每次通话，从1开始。可同时召开。
func nextId() uint64 { return uint64(atomic.AddUint32(&lastId, 1)) }

// TypeParam表示类型参数类型。
type TypeParam struct {
	check *Checker  // 用于惰性类型绑定完成
	id    uint64    // 唯一id，仅用于调试
	obj   *TypeName // 对应的类型名称
	index int       // 按源顺序键入参数索引，从0开始
	bound Type      // *命名或*接口；基础类型始终是*接口
}

// Obj返回类型参数t的类型名称。
func (t *TypeParam) Obj() *TypeName { return t.obj }

// NewTypeParam返回一个新的TypeParam。
func (check *Checker) NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam {
	assert(bound != nil)
	typ := &TypeParam{check: check, id: nextId(), obj: obj, index: index, bound: bound}
	if obj.typ == nil {
		obj.typ = typ
	}
	return typ
}

func (t *TypeParam) Bound() *Interface {
	iface := asInterface(t.bound)
	// 使用类型绑定位置（如果有）
	pos := nopos
	if n, _ := t.bound.(*Named); n != nil {
		pos = n.obj.pos
	}
	// TODO（gri）在Checker上将其切换为未报告的方法。
	t.check.completeInterface(pos, iface)
	return iface
}

// optype返回类型的操作类型。除了
// 类型参数，操作类型相同
// 作为基础类型（由下返回）。对于
// 类型参数，则确定操作类型
// 通过相应类型绑定的类型列表。这个
// 结果可能是底部或顶部类型，但决不是
// 传入类型参数。
func optype(typ Type) Type {
	if t := asTypeParam(typ); t != nil {
		// 如果optype是typ，则返回前面的类型
		// 没有消息。它还可以防止无限递归
		// 通过asTypeParam转换器功能。这是可能发生的
		// 对于表单的类型参数列表：
		// （类型T接口{类型T}）。
		// 另见第39680期。
		if u := t.Bound().allTypes; u != nil && u != typ {
			// u！=typ和u是类型参数=>在（u）！=典型，所以这是好的
			return under(u)
		}
		return theTop
	}
	return under(typ)
}

// 实例在语法上表示实例化的泛型类型
// （不展开实例化）。仅显示类型实例
// 在类型检查期间，由其完全实例化的
// 在类型检查结束之前（展开）类型。
type instance struct {
	check   *Checker     // 用于延迟实例化
	pos     syntax.Pos   // 类型实例化的位置；仅适用于错误报告
	base    *Named       // 要实例化的参数化类型
	targs   []Type       // 类型参数
	poslist []syntax.Pos // 每个目标的位置；仅适用于错误报告
	value   Type         // 实例化后的基（目标…）或类型[无效]；如果尚未设置，则为零
}

// expand返回t的实例化（=扩展）类型。
// 结果是实例化的*命名类型，或者
// 如果出现错误，则为Typ[无效]。
func (t *instance) expand() Type {
	v := t.value
	if v == nil {
		v = t.check.instantiate(t.pos, t.base, t.targs, t.poslist)
		if v == nil {
			v = Typ[Invalid]
		}
		t.value = v
	}
	// 实例化后，必须有一个无效的或*命名的类型。
	if debug && v != Typ[Invalid] {
		_ = v.(*Named)
	}
	return v
}

// expand将类型实例扩展为其实例化实例
// 输入并保留所有其他类型。扩展
// 不会重现。
func expand(typ Type) Type {
	if t, _ := typ.(*instance); t != nil {
		return t.expand()
	}
	return typ
}

// expandf设置为展开。
// 调用expand时调用expandf会导致编译时间周期错误。
var expandf func(Type) Type

func init() { expandf = expand }

// “底部”表示类型晶格的底部。
// 它是类型参数的基础类型
// 无法满足任何类型的要求，通常是因为
// 类型约束的交集没有留下任何内容）。
type bottom struct{}

// 底部是单件底部类型。
var theBottom = &bottom{}

// top表示类型晶格的顶部。
// 它是类型参数的基础类型
// 可由任何类型（忽略方法）满足，
// 通常是因为类型约束没有类型
// 列表
type top struct{}

// 顶部是单体顶部类型。
var theTop = &top{}

// 底层应用程序的特定于类型的实现。
func (t *Basic) Underlying() Type     { return t }
func (t *Array) Underlying() Type     { return t }
func (t *Slice) Underlying() Type     { return t }
func (t *Struct) Underlying() Type    { return t }
func (t *Pointer) Underlying() Type   { return t }
func (t *Tuple) Underlying() Type     { return t }
func (t *Signature) Underlying() Type { return t }
func (t *Sum) Underlying() Type       { return t }
func (t *Interface) Underlying() Type { return t }
func (t *Map) Underlying() Type       { return t }
func (t *Chan) Underlying() Type      { return t }
func (t *Named) Underlying() Type     { return t.underlying }
func (t *TypeParam) Underlying() Type { return t }
func (t *instance) Underlying() Type  { return t }
func (t *bottom) Underlying() Type    { return t }
func (t *top) Underlying() Type       { return t }

// 字符串的类型特定实现。
func (t *Basic) String() string     { return TypeString(t, nil) }
func (t *Array) String() string     { return TypeString(t, nil) }
func (t *Slice) String() string     { return TypeString(t, nil) }
func (t *Struct) String() string    { return TypeString(t, nil) }
func (t *Pointer) String() string   { return TypeString(t, nil) }
func (t *Tuple) String() string     { return TypeString(t, nil) }
func (t *Signature) String() string { return TypeString(t, nil) }
func (t *Sum) String() string       { return TypeString(t, nil) }
func (t *Interface) String() string { return TypeString(t, nil) }
func (t *Map) String() string       { return TypeString(t, nil) }
func (t *Chan) String() string      { return TypeString(t, nil) }
func (t *Named) String() string     { return TypeString(t, nil) }
func (t *TypeParam) String() string { return TypeString(t, nil) }
func (t *instance) String() string  { return TypeString(t, nil) }
func (t *bottom) String() string    { return TypeString(t, nil) }
func (t *top) String() string       { return TypeString(t, nil) }

// 返回真正的扩展基础类型。
// 如果不存在，则结果为Typ[Invalid]。
// 只有在已知类型时才能调用下
// 完全设置。
func under(t Type) Type {
	// TODO（gri）这对*Sum正确吗？
	if n := asNamed(t); n != nil {
		return n.under()
	}
	return t
}

// 转换器
// None
// 仅当类型为时才能调用转换器
// 已知已完全设置。转换器返回
// 类型的操作类型（请参见optype注释）
// 如果类型参数不是
// 各自的类型。

func asBasic(t Type) *Basic {
	op, _ := optype(t).(*Basic)
	return op
}

func asArray(t Type) *Array {
	op, _ := optype(t).(*Array)
	return op
}

func asSlice(t Type) *Slice {
	op, _ := optype(t).(*Slice)
	return op
}

func asStruct(t Type) *Struct {
	op, _ := optype(t).(*Struct)
	return op
}

func asPointer(t Type) *Pointer {
	op, _ := optype(t).(*Pointer)
	return op
}

// 不需要一个耦合-未提供

func asSignature(t Type) *Signature {
	op, _ := optype(t).(*Signature)
	return op
}

func asSum(t Type) *Sum {
	op, _ := optype(t).(*Sum)
	return op
}

func asInterface(t Type) *Interface {
	op, _ := optype(t).(*Interface)
	return op
}

func asMap(t Type) *Map {
	op, _ := optype(t).(*Map)
	return op
}

func asChan(t Type) *Chan {
	op, _ := optype(t).(*Chan)
	return op
}

// 如果asNamed和asTypeParam的参数属于各自的类型
// （可能在扩展实例类型之后），这些方法返回该类型。
// 否则结果为零。

func asNamed(t Type) *Named {
	e, _ := expand(t).(*Named)
	return e
}

func asTypeParam(t Type) *TypeParam {
	u, _ := under(t).(*TypeParam)
	return u
}

// 为编译器导出。

func AsPointer(t Type) *Pointer     { return asPointer(t) }
func AsNamed(t Type) *Named         { return asNamed(t) }
func AsSignature(t Type) *Signature { return asSignature(t) }
func AsInterface(t Type) *Interface { return asInterface(t) }
